#include "spk_camera.h"
#include "config.h"
#include "sip_client.h"
#include "rtp_send_ps.h"

#define LOG_TAG "rtp_send_ps"
#define LOG_LVL LOG_LVL_INFO
#include "spk_ulog.h"

cls_rtp_send_ps::cls_rtp_send_ps(cls_sip_client *p_sip_client)
{
    sip_client = p_sip_client;

    video_queue = sip_client->app->video_queue;
    audio_queue = sip_client->app->audio_queue;

    // use_tcp = sip_client->cfg_cur->sip_protocal_type;
    use_tcp = 0;  //  暂时使用 udp 的方式来推送 rtp 流

    socket_fd = -1;
    local_port = sip_client->sip_config.local_rtp_port;
    server_port = sip_client->sip_config.server_rtp_port;
    server_ip = sip_client->sip_config.server_ip;

    if (use_tcp)
        init_tcp();
    else
        init_udp();
}

cls_rtp_send_ps::~cls_rtp_send_ps()
{
    if (socket_fd > -1)
    {
        close(socket_fd);
        socket_fd = -1;
    }
}

void cls_rtp_send_ps::sendps_main_loop()
{
    init_packer();

    // clear the old date in queue
    msgq_get_last(video_queue, vid_buf, sizeof(vid_buf) - PES_HDR_LEN);
    msgq_get_last(audio_queue, aud_buf, sizeof(aud_buf) - PES_HDR_LEN);

    u8 *pData = (u8 *)malloc(VIDEO_MAX_SIZE * sizeof(u8));

    while (sendps_running)
    {
        if (0 == recv_msg_queue(video_queue, vid_buf + PES_HDR_LEN, sizeof(vid_buf) - PES_HDR_LEN))
        {
            u16 vid_len = vid_buf[PES_HDR_LEN + 0] + vid_buf[PES_HDR_LEN + 1] * 256; // the len saved in first 2 bit
            memcpy(pData, vid_buf + PES_HDR_LEN + 2, vid_len);                       // get the real data of the video frame

            if (vid_len == 0)
            {
                continue;
            }
            LOG_D("cur frame len = %d", vid_len);

            // set the I Frame
            unsigned char nalut = 0;
            if (pData[3] == 1)
                nalut = pData[4];
            else if (pData[2] == 1)
                nalut = pData[3];
            pPacker.IFrame = ((nalut & 0x1F) == 7);

            memcpy(vid_buf + PES_HDR_LEN, pData, vid_len); // the copy the real data to buff

            // LOG_D("[Debug] [%s:%d %s()] fd = %d", __FILE__, __LINE__, __func__, socket_fd);
            gb28181_streampackageForH264((char *)(vid_buf + PES_HDR_LEN), vid_len, &pPacker, 0);
            // LOG_D("[Debug] [%s:%d %s()] fd = %d", __FILE__, __LINE__, __func__, socket_fd);

            static struct timeval t0, t1;
            gettimeofday(&t1, NULL);

            int diff = (t1.tv_sec * 1000 + t1.tv_usec / 1000) - (t0.tv_sec * 1000 + t0.tv_usec / 1000);
            t0.tv_usec = t1.tv_usec;
            t0.tv_sec = t1.tv_sec;

            if (0 == recv_msg_queue(audio_queue, aud_buf + PES_HDR_LEN, sizeof(aud_buf) - PES_HDR_LEN))
            {
                int aud_size = AUDIO_SIZE;
                /*Audio frame format PS+PESA*/
                pPacker.IFrame = 0;

                // LOG_D("[Debug] [%s:%d %s()] fd = %d", __FILE__, __LINE__, __func__, socket_fd);
                gb28181_streampackageForH264(aud_buf + PES_HDR_LEN, aud_size, &pPacker, 1);
                // LOG_D("[Debug] [%s:%d %s()] fd = %d", __FILE__, __LINE__, __func__, socket_fd);
            }

            pPacker.s64CurPts += (uint64_t)(90000.0 / diff);
        }
        if (socket_fd == 0)
        {
            while (1)
                sleep(10);
        }
    }

    free(pData);
    pData = nullptr;
}

void cls_rtp_send_ps::sendps_loop_start()
{
    sendps_running = true;

    main_loop_thread = std::make_unique<std::thread>([this]()
                                                     {
                                                         sendps_main_loop(); // 直接调用非静态成员函数
                                                     });
}

void cls_rtp_send_ps::sendps_loop_stop()
{
    sendps_running = false;

    if (main_loop_thread && main_loop_thread->joinable())
    {
        main_loop_thread->join();
    }
}

void cls_rtp_send_ps::init_packer()
{
    pPacker.IFrame = 1; // 这是只是初始化, 当前帧是否是 I 帧还需要后期判断
    pPacker.u16CSeq = 0;
    pPacker.u32Ssrc = sip_client->sip_config.ssrc;
    pPacker.s64CurPts = 0;
}

void cls_rtp_send_ps::init_tcp()
{
    if ((socket_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1)
    {
        LOG_E("create socket failed");

        return;
    }

    // 关键改进：添加SO_REUSEADDR选项
    int reuse = 1;
    if (setsockopt(socket_fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0)
    {
        LOG_E("setsockopt(SO_REUSEADDR) failed");
        close(socket_fd);
        return;
    }

    int ret;
    sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_port = htons(local_port);
    addr.sin_addr.s_addr = INADDR_ANY;
    socklen_t addr_len = sizeof(struct sockaddr_in);

    ret = bind(socket_fd, (struct sockaddr *)&addr, addr_len);
    printf("local_port = %d\n", local_port);
    if (ret < 0)
    {
        LOG_E("bind socket failed");
        return;
    }

    int ss = 1024 * 1024;
    int len = 4;
    int err = setsockopt(socket_fd, SOL_SOCKET, SO_SNDBUF, (char *)&ss, len);
    err = getsockopt(socket_fd, SOL_SOCKET, SO_SNDBUF, (char *)&ss, (socklen_t *)&len);
    printf("%d\n", ss);

    sockaddr_in dest;
    dest.sin_family = AF_INET;
    dest.sin_port = htons(server_port);
    dest.sin_addr.s_addr = inet_addr(server_ip.c_str());

    while (1)
    {
        ret = connect(socket_fd, (const struct sockaddr *)&dest, addr_len);
        if (ret < 0)
        {
            printf("connect to server %s:%d failed\n", server_ip.c_str(), server_port);
        }
        else
        {
            printf("connect to server %s:%d success\n", server_ip.c_str(), server_port);
            break;
        }
        sleep(2);
    }
}

void cls_rtp_send_ps::init_udp()
{
    if ((socket_fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
    {
        LOG_E("create socket failed");
        return;
    }
    int ret;
    sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_port = htons(local_port);

    addr.sin_addr.s_addr = INADDR_ANY;
    socklen_t addr_len = sizeof(struct sockaddr_in);

    ret = bind(socket_fd, (struct sockaddr *)&addr, addr_len);
    if (ret < 0)
    {
        LOG_E("bind socket failed");
        return;
    }

    int ss = 1024 * 1024;
    int len = 4;
    int err = setsockopt(socket_fd, SOL_SOCKET, SO_SNDBUF, (char *)&ss, len);
    err = getsockopt(socket_fd, SOL_SOCKET, SO_SNDBUF, (char *)&ss, (socklen_t *)&len);
    printf("%d\n", ss);

    int ul = 1;
    ret = ioctl(socket_fd, FIONBIO, &ul); // 设置为非阻塞模式

    if (ret == -1)
    {
        LOG_E("设置套接字非阻塞失败");
        return;
    }
}

int cls_rtp_send_ps::gb28181_streampackageForH264(char *pData, int nFrameLen, Data_Info_s *pPacker, int stream_type)
{
    char szTempPacketHead[256];
    int nSizePos = 0;
    int nSize = 0;
    char *pBuff = NULL;
    memset(szTempPacketHead, 0, 256);
    // 1 package for ps header
    gb28181_make_ps_header(szTempPacketHead + nSizePos, pPacker->s64CurPts);
    nSizePos += PS_HDR_LEN;
    // 2 system header
    if (pPacker->IFrame == 1)
    {
        gb28181_make_sys_header(szTempPacketHead + nSizePos);
        nSizePos += SYS_HDR_LEN;

        gb28181_make_psm_header(szTempPacketHead + nSizePos);
        nSizePos += PSM_HDR_LEN;
    }

    if (gb28181_send_rtp_pack(szTempPacketHead, nSizePos, 0, pPacker) != 0)
        return -1;

    pBuff = pData - PES_HDR_LEN;
    while (nFrameLen > 0)
    {
        nSize = (nFrameLen > PS_PES_PAYLOAD_SIZE) ? PS_PES_PAYLOAD_SIZE : nFrameLen;
        gb28181_make_pes_header(pBuff, stream_type ? 0xC0 : 0xE0, nSize, pPacker->s64CurPts, pPacker->s64CurPts);

        if (gb28181_send_rtp_pack(pBuff, nSize + PES_HDR_LEN, ((nSize == nFrameLen) ? 1 : 0), pPacker) != 0)
        {
            LOG_E("gb28181_send_rtp_pack error");
            return -1;
        }
        nFrameLen -= nSize;
        pBuff += nSize;
    }

    return 0;
}

int cls_rtp_send_ps::gb28181_make_ps_header(char *pData, unsigned long long s64Scr)
{
    unsigned long long lScrExt = (s64Scr) % 100;
    // s64Scr = s64Scr / 100;

    // 这里除以100是由于sdp协议返回的video的频率是90000，帧率是25帧/s，所以每次递增的量是3600,
    // 所以实际你应该根据你自己编码里的时间戳来处理以保证时间戳的增量为3600即可，
    // 如果这里不对的话，就可能导致卡顿现象了
    bits_buffer_s bitsBuffer;
    bitsBuffer.i_size = PS_HDR_LEN;
    bitsBuffer.i_data = 0;
    bitsBuffer.i_mask = 0x80; // 二进制：10000000 这里是为了后面对一个字节的每一位进行操作，避免大小端夸字节字序错乱
    bitsBuffer.p_data = (unsigned char *)(pData);
    memset(bitsBuffer.p_data, 0, PS_HDR_LEN);
    bits_write(&bitsBuffer, 32, 0x000001BA);              /*start codes*/
    bits_write(&bitsBuffer, 2, 1);                        /*marker bits '01b'*/
    bits_write(&bitsBuffer, 3, (s64Scr >> 30) & 0x07);    /*System clock [32..30]*/
    bits_write(&bitsBuffer, 1, 1);                        /*marker bit*/
    bits_write(&bitsBuffer, 15, (s64Scr >> 15) & 0x7FFF); /*System clock [29..15]*/
    bits_write(&bitsBuffer, 1, 1);                        /*marker bit*/
    bits_write(&bitsBuffer, 15, s64Scr & 0x7fff);         /*System clock [14..0]*/
    bits_write(&bitsBuffer, 1, 1);                        /*marker bit*/
    bits_write(&bitsBuffer, 9, lScrExt & 0x01ff);         /*System clock ext*/
    bits_write(&bitsBuffer, 1, 1);                        /*marker bit*/
    bits_write(&bitsBuffer, 22, (255) & 0x3fffff);        /*bit rate(n units of 50 bytes per second.)*/
    bits_write(&bitsBuffer, 2, 3);                        /*marker bits '11'*/
    bits_write(&bitsBuffer, 5, 0x1f);                     /*reserved(reserved for future use)*/
    bits_write(&bitsBuffer, 3, 0);                        /*stuffing length*/
    return 0;
}

int cls_rtp_send_ps::gb28181_make_sys_header(char *pData)
{
    bits_buffer_s bitsBuffer;
    bitsBuffer.i_size = SYS_HDR_LEN;
    bitsBuffer.i_data = 0;
    bitsBuffer.i_mask = 0x80;
    bitsBuffer.p_data = (unsigned char *)(pData);
    memset(bitsBuffer.p_data, 0, SYS_HDR_LEN);
    /*system header*/
    bits_write(&bitsBuffer, 32, 0x000001BB);      /*start code*/
    bits_write(&bitsBuffer, 16, SYS_HDR_LEN - 6); /*header_length 表示次字节后面的长度，后面的相关头也是次意思*/
    bits_write(&bitsBuffer, 1, 1);                /*marker_bit*/
    bits_write(&bitsBuffer, 22, 50000);           /*rate_bound*/
    bits_write(&bitsBuffer, 1, 1);                /*marker_bit*/
    bits_write(&bitsBuffer, 6, 1);                /*audio_bound*/
    bits_write(&bitsBuffer, 1, 0);                /*fixed_flag */
    bits_write(&bitsBuffer, 1, 1);                /*CSPS_flag */
    bits_write(&bitsBuffer, 1, 1);                /*system_audio_lock_flag*/
    bits_write(&bitsBuffer, 1, 1);                /*system_video_lock_flag*/
    bits_write(&bitsBuffer, 1, 1);                /*marker_bit*/
    bits_write(&bitsBuffer, 5, 1);                /*video_bound*/
    bits_write(&bitsBuffer, 1, 0);                /*dif from mpeg1*/
    bits_write(&bitsBuffer, 7, 0x7F);             /*reserver*/
    /*audio stream bound*/
    bits_write(&bitsBuffer, 8, 0xC0); /*stream_id*/
    bits_write(&bitsBuffer, 2, 3);    /*marker_bit */
    bits_write(&bitsBuffer, 1, 0);    /*PSTD_buffer_bound_scale*/
    bits_write(&bitsBuffer, 13, 512); /*PSTD_buffer_size_bound*/
    /*video stream bound*/
    bits_write(&bitsBuffer, 8, 0xE0);  /*stream_id*/
    bits_write(&bitsBuffer, 2, 3);     /*marker_bit */
    bits_write(&bitsBuffer, 1, 1);     /*PSTD_buffer_bound_scale*/
    bits_write(&bitsBuffer, 13, 2048); /*PSTD_buffer_size_bound*/
    return 0;
}

int cls_rtp_send_ps::gb28181_make_psm_header(char *pData)
{
    bits_buffer_s bitsBuffer;
    bitsBuffer.i_size = PSM_HDR_LEN;
    bitsBuffer.i_data = 0;
    bitsBuffer.i_mask = 0x80;
    bitsBuffer.p_data = (unsigned char *)(pData);
    memset(bitsBuffer.p_data, 0, PSM_HDR_LEN);
    bits_write(&bitsBuffer, 24, 0x000001); /*start code*/
    bits_write(&bitsBuffer, 8, 0xBC);      /*map stream id*/
    bits_write(&bitsBuffer, 16, 18);       /*program stream map length*/
    bits_write(&bitsBuffer, 1, 1);         /*current next indicator */
    bits_write(&bitsBuffer, 2, 3);         /*reserved*/
    bits_write(&bitsBuffer, 5, 0);         /*program stream map version*/
    bits_write(&bitsBuffer, 7, 0x7F);      /*reserved */
    bits_write(&bitsBuffer, 1, 1);         /*marker bit */
    bits_write(&bitsBuffer, 16, 0);        /*programe stream info length*/
    bits_write(&bitsBuffer, 16, 8);        /*elementary stream map length  is*/
    /*audio*/
    bits_write(&bitsBuffer, 8, 0x90); /*stream_type*/
    bits_write(&bitsBuffer, 8, 0xC0); /*elementary_stream_id*/
    bits_write(&bitsBuffer, 16, 0);   /*elementary_stream_info_length is*/
    /*video*/
    bits_write(&bitsBuffer, 8, 0x1B); /*stream_type*/
    bits_write(&bitsBuffer, 8, 0xE0); /*elementary_stream_id*/
    bits_write(&bitsBuffer, 16, 0);   /*elementary_stream_info_length */
    /*crc (2e b9 0f 3d)*/
    bits_write(&bitsBuffer, 8, 0x45); /*crc (24~31) bits*/
    bits_write(&bitsBuffer, 8, 0xBD); /*crc (16~23) bits*/
    bits_write(&bitsBuffer, 8, 0xDC); /*crc (8~15) bits*/
    bits_write(&bitsBuffer, 8, 0xF4); /*crc (0~7) bits*/
    return 0;
}

int cls_rtp_send_ps::gb28181_make_pes_header(char *pData, int stream_id, int payload_len, unsigned long long pts, unsigned long long dts)
{
    bits_buffer_s bitsBuffer;
    bitsBuffer.i_size = PES_HDR_LEN;
    bitsBuffer.i_data = 0;
    bitsBuffer.i_mask = 0x80;
    bitsBuffer.p_data = (unsigned char *)(pData);
    memset(bitsBuffer.p_data, 0, PES_HDR_LEN);
    /*system header*/
    bits_write(&bitsBuffer, 24, 0x000001);                          /*start code*/
    bits_write(&bitsBuffer, 8, (stream_id));                        /*streamID*/
    bits_write(&bitsBuffer, 16, (payload_len) + 13); /*packet_len*/ // 指出pes分组中数据长度和该字节后的长度和
    bits_write(&bitsBuffer, 2, 2);                                  /*'10'*/
    bits_write(&bitsBuffer, 2, 0);                                  /*scrambling_control*/
    bits_write(&bitsBuffer, 1, 0);                                  /*priority*/
    bits_write(&bitsBuffer, 1, 0);                                  /*data_alignment_indicator*/
    bits_write(&bitsBuffer, 1, 0);                                  /*copyright*/
    bits_write(&bitsBuffer, 1, 0);                                  /*original_or_copy*/
    bits_write(&bitsBuffer, 1, 1);                                  /*PTS_flag*/
    bits_write(&bitsBuffer, 1, 1);                                  /*DTS_flag*/
    bits_write(&bitsBuffer, 1, 0);                                  /*ESCR_flag*/
    bits_write(&bitsBuffer, 1, 0);                                  /*ES_rate_flag*/
    bits_write(&bitsBuffer, 1, 0);                                  /*DSM_trick_mode_flag*/
    bits_write(&bitsBuffer, 1, 0);                                  /*additional_copy_info_flag*/
    bits_write(&bitsBuffer, 1, 0);                                  /*PES_CRC_flag*/
    bits_write(&bitsBuffer, 1, 0);                                  /*PES_extension_flag*/
    bits_write(&bitsBuffer, 8, 10);                                 /*header_data_length*/
    // 指出包含在 PES 分组标题中的可选字段和任何填充字节所占用的总字节数。该字段之前
    // 的字节指出了有无可选字段。

    /*PTS,DTS*/
    bits_write(&bitsBuffer, 4, 3);                    /*'0011'*/
    bits_write(&bitsBuffer, 3, ((pts) >> 30) & 0x07); /*PTS[32..30]*/
    bits_write(&bitsBuffer, 1, 1);
    bits_write(&bitsBuffer, 15, ((pts) >> 15) & 0x7FFF); /*PTS[29..15]*/
    bits_write(&bitsBuffer, 1, 1);
    bits_write(&bitsBuffer, 15, (pts) & 0x7FFF); /*PTS[14..0]*/
    bits_write(&bitsBuffer, 1, 1);
    bits_write(&bitsBuffer, 4, 1);                    /*'0001'*/
    bits_write(&bitsBuffer, 3, ((dts) >> 30) & 0x07); /*DTS[32..30]*/
    bits_write(&bitsBuffer, 1, 1);
    bits_write(&bitsBuffer, 15, ((dts) >> 15) & 0x7FFF); /*DTS[29..15]*/
    bits_write(&bitsBuffer, 1, 1);
    bits_write(&bitsBuffer, 15, (dts) & 0x7FFF); /*DTS[14..0]*/
    bits_write(&bitsBuffer, 1, 1);
    return 0;
}

int cls_rtp_send_ps::gb28181_send_rtp_pack(char *databuff, int nDataLen, int mark_flag, Data_Info_s *pPacker)
{
    /***
     *_______________#########_______________________
     *______________############_____________________
     *______________#############____________________
     *_____________##__###########___________________
     *____________###__######_#####__________________
     *____________###_#######___####_________________
     *___________###__##########_####________________
     *__________####__###########_####_______________
     *________#####___###########__#####_____________
     *_______######___###_########___#####___________
     *_______#####___###___########___######_________
     *______######___###__###########___######_______
     *_____######___####_##############__######______
     *____#######__#####################_#######_____
     *____#######__##############################____
     *___#######__######_#################_#######___
     *___#######__######_######_#########___######___
     *___#######____##__######___######_____######___
     *___#######________######____#####_____#####____
     *____######________#####_____#####_____####_____
     *_____#####________####______#####_____###______
     *______#####______;###________###______#________
     *________##_______####________####______________
     */
    if (use_tcp)
    {
        int nRes = 0;
        int nPlayLoadLen = 0;
        int nSendSize = 0;
        char szRtpHdr[RTP_HDR_LEN];
        memset(szRtpHdr, 0, RTP_HDR_LEN);

        if (nDataLen + RTP_HDR_LEN <= RTP_MAX_PACKET_BUFF) // 1460 pPacker指针本来有一个1460大小的buffer数据缓存
        {
            // 一帧数据发送完后，给mark标志位置1
            gb28181_make_rtp_header(szRtpHdr, ((mark_flag == 1) ? 1 : 0), ++pPacker->u16CSeq, pPacker->s64CurPts, pPacker->u32Ssrc);
            short len = RTP_HDR_LEN + nDataLen;
            len = htons(len);
            memcpy(pPacker->szBuff, &len, 2);
            memcpy(pPacker->szBuff + 2, szRtpHdr, RTP_HDR_LEN);
            memcpy(pPacker->szBuff + RTP_HDR_LEN + 2, databuff, nDataLen);
            nRes = SendDataBuff(pPacker->szBuff, nDataLen + RTP_HDR_LEN + 2);
            if (nRes != (RTP_HDR_LEN + nDataLen + 2))
            {
                printf("nRes = %d\n", nRes);
                printf(" tcp send error !\n");
                return -1;
            }
        }
        else
        {
            nPlayLoadLen = RTP_MAX_PACKET_BUFF - RTP_HDR_LEN; // 每次只能发送的数据长度 除去rtp头
            gb28181_make_rtp_header(pPacker->szBuff + 2, 0, ++pPacker->u16CSeq, pPacker->s64CurPts, pPacker->u32Ssrc);
            short len = RTP_HDR_LEN + nPlayLoadLen;
            len = htons(len);
            memcpy(pPacker->szBuff, &len, 2);
            memcpy(pPacker->szBuff + RTP_HDR_LEN + 2, databuff, nPlayLoadLen);
            nRes = SendDataBuff(pPacker->szBuff, RTP_HDR_LEN + nPlayLoadLen + 2); // 这个地方越界了,  所以把szBuff加长了2个字节
            if (nRes != (RTP_HDR_LEN + nPlayLoadLen + 2))
            {
                LOG_E("SendDataBuff error");
                return -1;
            }

            nDataLen -= nPlayLoadLen;
            // databuff += (nPlayLoadLen - RTP_HDR_LEN);
            databuff += nPlayLoadLen;    // 表明前面到数据已经发送出去
            databuff -= RTP_HDR_LEN + 2; // 用来存放rtp头
            while (nDataLen > 0)
            {
                if (nDataLen <= nPlayLoadLen)
                {
                    // 一帧数据发送完，置mark标志位
                    gb28181_make_rtp_header(databuff + 2, mark_flag, ++pPacker->u16CSeq, pPacker->s64CurPts, pPacker->u32Ssrc);
                    nSendSize = nDataLen;
                    len = nSendSize + RTP_HDR_LEN;
                    len = htons(len);
                    memcpy(databuff, &len, 2);
                }
                else
                {
                    gb28181_make_rtp_header(databuff + 2, 0, ++pPacker->u16CSeq, pPacker->s64CurPts, pPacker->u32Ssrc);
                    nSendSize = nPlayLoadLen;
                    len = nSendSize + RTP_HDR_LEN;
                    len = htons(len);
                    memcpy(databuff, &len, 2);
                }

                nRes = SendDataBuff(databuff, RTP_HDR_LEN + nSendSize + 2);
                if (nRes != (RTP_HDR_LEN + nSendSize + 2))
                {
                    LOG_E("SendDataBuff error");
                    return -1;
                }
                nDataLen -= nSendSize;
                databuff += nSendSize;
                // 因为buffer指针已经向后移动一次rtp头长度后，
                // 所以每次循环发送rtp包时，只要向前移动裸数据到长度即可，这是buffer指针实际指向到位置是
                // databuff向后重复的rtp长度的裸数据到位置上
            }
        }
    }
    else
    {
        int nRes = 0;
        int nPlayLoadLen = 0;
        int nSendSize = 0;
        char szRtpHdr[RTP_HDR_LEN];
        memset(szRtpHdr, 0, RTP_HDR_LEN);

        if (nDataLen + RTP_HDR_LEN <= RTP_MAX_PACKET_BUFF) // 1460 pPacker指针本来有一个1460大小的buffer数据缓存
        {
            // 一帧数据发送完后，给mark标志位置1
            gb28181_make_rtp_header(szRtpHdr, ((mark_flag == 1) ? 1 : 0), ++pPacker->u16CSeq, pPacker->s64CurPts, pPacker->u32Ssrc);
            memcpy(pPacker->szBuff, szRtpHdr, RTP_HDR_LEN);
            memcpy(pPacker->szBuff + RTP_HDR_LEN, databuff, nDataLen);
            LOG_D("nDataLen + RTP_HDR_LEN = %d", nDataLen + RTP_HDR_LEN);
            nRes = SendDataBuff(pPacker->szBuff, nDataLen + RTP_HDR_LEN);
            LOG_D("nRes = %d", nRes);
            if (nRes != (RTP_HDR_LEN + nDataLen))
            {
                printf(" udp send error !\n");
                return -1;
            }
        }
        else
        {
            nPlayLoadLen = RTP_MAX_PACKET_BUFF - RTP_HDR_LEN; // 每次只能发送的数据长度 除去rtp头
            gb28181_make_rtp_header(pPacker->szBuff, 0, ++pPacker->u16CSeq, pPacker->s64CurPts, pPacker->u32Ssrc);
            memcpy(pPacker->szBuff + RTP_HDR_LEN, databuff, nPlayLoadLen);
            nRes = SendDataBuff(pPacker->szBuff, RTP_HDR_LEN + nPlayLoadLen);
            if (nRes != (RTP_HDR_LEN + nPlayLoadLen))
            {
                LOG_E("SendDataBuff error");
                return -1;
            }

            nDataLen -= nPlayLoadLen;
            // databuff += (nPlayLoadLen - RTP_HDR_LEN);
            databuff += nPlayLoadLen; // 表明前面到数据已经发送出去
            databuff -= RTP_HDR_LEN;  // 用来存放rtp头
            while (nDataLen > 0)
            {
                if (nDataLen <= nPlayLoadLen)
                {
                    // 一帧数据发送完，置mark标志位
                    gb28181_make_rtp_header(databuff, mark_flag, ++pPacker->u16CSeq, pPacker->s64CurPts, pPacker->u32Ssrc);
                    nSendSize = nDataLen;
                }
                else
                {
                    gb28181_make_rtp_header(databuff, 0, ++pPacker->u16CSeq, pPacker->s64CurPts, pPacker->u32Ssrc);
                    nSendSize = nPlayLoadLen;
                }

                nRes = SendDataBuff(databuff, RTP_HDR_LEN + nSendSize);
                if (nRes != (RTP_HDR_LEN + nSendSize))
                {
                    LOG_E("SendDataBuff error");
                    return -1;
                }
                nDataLen -= nSendSize;
                databuff += nSendSize;
                // 因为buffer指针已经向后移动一次rtp头长度后，
                // 所以每次循环发送rtp包时，只要向前移动裸数据到长度即可，这是buffer指针实际指向到位置是
                // databuff向后重复的rtp长度的裸数据到位置上
            }
        }
    }

    return 0;
}

int cls_rtp_send_ps::gb28181_make_rtp_header(char *pData, int marker_flag, unsigned short cseq, long long curpts, unsigned int ssrc)
{
    bits_buffer_s bitsBuffer;
    if (pData == NULL)
        return -1;
    bitsBuffer.i_size = RTP_HDR_LEN;
    bitsBuffer.i_data = 0;
    bitsBuffer.i_mask = 0x80;
    bitsBuffer.p_data = (unsigned char *)(pData);
    memset(bitsBuffer.p_data, 0, RTP_HDR_LEN);
    bits_write(&bitsBuffer, 2, RTP_VERSION);   /* rtp version  */
    bits_write(&bitsBuffer, 1, 0);             /* rtp padding  */
    bits_write(&bitsBuffer, 1, 0);             /* rtp extension  */
    bits_write(&bitsBuffer, 4, 0);             /* rtp CSRC count */
    bits_write(&bitsBuffer, 1, (marker_flag)); /* rtp marker   */
    bits_write(&bitsBuffer, 7, 96);            /* rtp payload type*/
    bits_write(&bitsBuffer, 16, (cseq));       /* rtp sequence    */
    bits_write(&bitsBuffer, 32, (curpts));     /* rtp timestamp   */
    bits_write(&bitsBuffer, 32, (ssrc));       /* rtp SSRC    */
    return 0;
}

int cls_rtp_send_ps::SendDataBuff(char *buff, int size)
{
    int ret;
    if (use_tcp)
    {
        ret = send(socket_fd, buff, size, MSG_NOSIGNAL); // send函数专用于TCP链接，sendto函数专用与UDP连接

        if (ret == -1)
        {
            if (errno == ECONNRESET)
            {
                perror("Connection reset by peer");
            }
            else
            {
                perror("send");
            }
        }
    }
    else
    {
        /* 设置address */
        struct sockaddr_in addr_serv;
        int len;
        memset(&addr_serv, 0, sizeof(addr_serv)); // memset 在一段内存块中填充某个给定的值, 它是对较大的结构体或数组进行清零操作的一种最快方法
        addr_serv.sin_family = AF_INET;
        addr_serv.sin_addr.s_addr = inet_addr(server_ip.c_str());
        addr_serv.sin_port = htons(server_port);
        len = sizeof(addr_serv);

        ret = sendto(socket_fd, buff, size, 0, (struct sockaddr *)&addr_serv, len);
    }

    return ret;
}
